package com.fjnu.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @desc:
 * @author: Ping
 * @date: 2025/10/10 8:34
 */

@Component
@Aspect
@Slf4j
@Order(1)
public class ExecutionAspect {
    /**
     * Part 1:  pointcut定义
     *     execution(<part0> <part1> <part2>)
     *       <part0>::=  public  |  private | *
     *       <part1>::=  return_expr  | *
     *       <part2>::=  method_expr | * | 包名.类名.方法名(参数列表)
     *      execution(public * com.fjnu.dao..*.*(..))
     *
     */
    @Pointcut("execution(public * com.fjnu.dao..*.delete*(..))")
    public void dayLayer(){}


    /**
     * Part 2:  advice定义
     */
    /**
     * 定义 Before logging advice, After logging advice
     * around logging advice, after-returning advice
     * after-throwing advice
     */
    /**
     * todo: 1. 定义 Before logging advice
     */
    @Before("dayLayer()")
    public void loggingBefore(JoinPoint jp) {
        log.info("Before-advice: " + jp.getSignature()
                .getName());

    }
    /**
     * todo: 2. 定义 After logging advice
     */
    @After("dayLayer()")
    public void loggingAfter(JoinPoint jp) {
        log.info("After-advice: " + jp.getSignature().getName()) ;
    }
    /**
     * todo: 3. 定义 around logging advice
     */
    @Around("dayLayer()")
    public Object loggingAround(ProceedingJoinPoint jp) throws Throwable {
        log.info("Around-advice before execution: " + jp.getSignature().getName());
        Object ret = null;
        try {
            ret = jp.proceed();
            log.info("Around-advice after execution : " + jp.getSignature().getName());
        } catch (Throwable e) {
            // after throwing
            log.info("Around-advice after throwing: " + jp.getSignature().getName());
        }

        log.info("Around-advice after execution: " + jp.getSignature().getName()) ;
        return ret ;
    }

    /**
     * todo: 4. 定义 after-returning advice
     */
    @AfterReturning(pointcut = "dayLayer()",
            returning = "ret")
    public void loggingAfterReturning(JoinPoint jp,
                                      Object ret) {
        log.info("After-returning method: "
                + jp.getSignature().getName()
                + ", ret=" + ret) ;
    }
    /**
     * todo: 5. 定义 after-throwing advice
     */
    @AfterThrowing(pointcut = "dayLayer()",
            throwing = "ex")
    public void loggingAfterThrowing(JoinPoint jp, Throwable ex) {
        log.error("After-throwing method: " + jp.getSignature().getName() + ", ex=" + ex.getMessage()) ;
    }


}
